package com.qdlc.p2p.biz.processor.task;

import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.qd.p2p.adapter.enums.ResponseCode;
import com.qdlc.p2p.biz.executer.impl.RechargeSuccessExecuter;
import com.qdlc.p2p.biz.processor.event.RechargeValueEvent;
import com.qdlc.p2p.common.core.queue.TaskProcessorException;
import com.qdlc.p2p.common.core.queue.ValueEvent;
import com.qdlc.p2p.common.core.queue.annotation.ScheduledProcessor;
import com.qdlc.p2p.common.util.LogFactory;
import com.qdlc.p2p.dal.dao.AccountRechargeDao;
import com.qdlc.p2p.dal.dto.AccountRecharge;
import com.qdlc.p2p.dal.dto.User;
import com.qdlc.p2p.dal.model.AccountRechargeModel;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.XppDriver;

/**
 * [网银充值] 充值回调
 * @author linya 2015-12-30
 */
@Service
@ScheduledProcessor(delay=2, step=2, timeunit=TimeUnit.MINUTES)
public class RechargeSuccessTaskProcessor extends AbstractTaskProcessor {

	private static final Logger logger = LogFactory.QUICK_PAY_LOGGER;
	
	@Resource
	AccountRechargeDao accountRechargeDao;
	
	@Override
	public boolean hasTransaction() {
		return true;
	}

	@Override
	public boolean supports(ValueEvent event) {
		return event instanceof RechargeValueEvent;
	}
	
	@Override
	public void process0(ValueEvent event) throws TaskProcessorException {
		RechargeValueEvent chargeEvent = (RechargeValueEvent)event;

		String notifyResponse = chargeEvent.getNotifyResponse();
		Recharge recharge = xml2Object(chargeEvent, notifyResponse);
		String code = recharge.getCode();
		String orderId = recharge.getOrderId();
		AccountRecharge accountRecharge = accountRechargeDao.getRechargeByTradeno(orderId);
        if (null == accountRecharge) {
            throw new TaskProcessorException(chargeEvent, "++++ 本地充值订单号" + orderId + "不存在...");
        }

		if (ResponseCode.CSD000.toString().equals(code)) {
			doSuccess(accountRecharge);
		} else {
			doFailure(accountRecharge);
		}
	}
	
	/**
	 * 充值成功
	 * @param recharge
	 */
	@Transactional(propagation=Propagation.REQUIRED)
	public void doSuccess(AccountRecharge recharge){
		recharge = accountRechargeDao.findWithLock(recharge.getId());
		//校验订单状态
        if (recharge.getStatus() == AccountRechargeModel.RECHARGE_SUCCESS) {
            logger.info("++++ 订单已经处理,订单号:" + recharge.getTradeNo());
            return;
        }
        User user = recharge.getUser();
        //处理充值业务
        recharge.setStatus(AccountRechargeModel.RECHARGE_SUCCESS);
        //添加资金记录
        RechargeSuccessExecuter rechargeSuccessExecuter = new RechargeSuccessExecuter();
        rechargeSuccessExecuter.setMoney(recharge.getMoney());
        rechargeSuccessExecuter.setRecharge(recharge);
        rechargeSuccessExecuter.execute(user);
        accountRechargeDao.update(recharge);
	}
	
	/**
	 * 充值失败
	 * @param recharge
	 */
	@Transactional(propagation=Propagation.REQUIRED)
	public void doFailure(AccountRecharge recharge){
		recharge = accountRechargeDao.findWithLock(recharge.getId());
        //校验订单状态
        if (recharge.getStatus() == AccountRechargeModel.RECHARGE_INVALID) {
            logger.info("++++ 订单已经处理,订单号:" + recharge.getTradeNo());
            return;
        }
        //设置订单状态
        recharge.setStatus(AccountRechargeModel.RECHARGE_INVALID);
        accountRechargeDao.update(recharge);
	}

	/**
	 * 将响应XML转成Recharge对象
	 * @param event
	 * @param responseString
	 * @return
	 * @throws TaskProcessorException
	 */
	protected Recharge xml2Object(ValueEvent event, String responseString) throws TaskProcessorException{
		Object object = null;
		try {
			XStream xstream = new XStream(new XppDriver(new NoNameCoder()));
			xstream.autodetectAnnotations(true);
			String alias;
			XStreamAlias xStreamAlias = Recharge.class.getAnnotation(XStreamAlias.class);
			if(xStreamAlias == null){
				alias = Recharge.class.getName();
			}else{
				alias = xStreamAlias.value();
			}
			xstream.alias(alias, Recharge.class);
			object = xstream.fromXML(responseString);
		} catch (Exception e) {
			throw new TaskProcessorException(event, "++++ 充值回调响应XML解析错误.");
		}
		return (Recharge)object;
	}
	
	/**
	 * 充值回调响应对象
	 */
	@XStreamAlias("crs")
	@SuppressWarnings("unused")
	private static class Recharge{
		
		@XStreamAlias("code")
		String code;
		
		@XStreamAlias("order_id")
		String orderId;
		
		@XStreamAlias("incash_money")
		String money;
		
		@XStreamAlias("fee")
		String fee;
		
		@XStreamAlias("mer_fee")
		String merFee;
		
		@XStreamAlias("fee_taken_on")
		String feeTakenOn;
		
		@XStreamAlias("additional_info")
		String additionalInfo;
		
		@XStreamAlias("succ_time")
		String successTime;

		public String getCode() {
			return code;
		}

		public void setCode(String code) {
			this.code = code;
		}

		public String getOrderId() {
			return orderId;
		}

		public void setOrderId(String orderId) {
			this.orderId = orderId;
		}

		public String getMoney() {
			return money;
		}

		public void setMoney(String money) {
			this.money = money;
		}

		public void setFee(String fee) {
			this.fee = fee;
		}

		public void setMerFee(String merFee) {
			this.merFee = merFee;
		}

		public void setFeeTakenOn(String feeTakenOn) {
			this.feeTakenOn = feeTakenOn;
		}

		public void setAdditionalInfo(String additionalInfo) {
			this.additionalInfo = additionalInfo;
		}

		public void setSuccessTime(String successTime) {
			this.successTime = successTime;
		}
		
	}
	
}
